﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Security;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Tcp;
using ForumServer;
using ForumServer.Forum;
using ForumServer.Logger;
using System.Threading;
using log4net;
using System.IO;
using System.Net.Sockets;

namespace ForumClient
{
    public class ForumClient
    {
        public static void Main(string[] args)
        {
            ILog logger = null;
            Authenticator auth = null;
            Forum forum = null;
            ClientConfiguration.configure(ref logger, ref auth, ref forum);
            ClientHandler clientHandler = new ClientHandler(ref logger);
            //--------------------------My Great Test Code-----------------------------------------------//

            User user = new User("Adiel", "password", "Ashrov@mail.com", "123", "Adiel", "Ashrov");
            User user3 = new User("Etai", "password", "Hazan@mail.com", "123", "Etai", "Hazan");
            Moderator user4 = new Moderator("Benny", "password", "Mihaeli@mail.com", "123", "Benny", "Mihaeli");
            User user5 = new User("Chezi", "password", "Halpert@mail.com", "123", "Chezi", "Halpert");

            auth.registerUser(user3);
            auth.registerModeratorUser(user4);
            auth.registerUser(user5);
            //--------------------------End of My Great Code-------------------------------------------//
            bool moderatorFlag = false;
            user = loginOrRegister(auth, ref logger, ref moderatorFlag);
            if (user == null)
                Console.WriteLine("could not locate server");
            
            else
            {

                Console.WriteLine("Welcome To The Forum\n");

                clientHandler.handleChooseAForum(ref forum, auth);//here we choose which forum we want to view.

                
                Console.WriteLine("Welcome To The Forum Server");

                while (true)
                {
                    Console.WriteLine("What would you like to do?");
                    Console.WriteLine("1.   View Forum Threads");
                    Console.WriteLine("2.   Add a Thread");
                    Console.WriteLine("3.   Remove a Thread");
                    Console.WriteLine("4.   Edit My Friends list");
                    Console.WriteLine("5.   Logout");
                    Console.WriteLine("6.   Choose an other forum");
                    Console.WriteLine("7.   Exit the system");
                    String option = Console.ReadLine();

                    if (String.IsNullOrEmpty(option))
                        continue;

                    
                    switch(option)
                    {
                        case "1":
                            try
                            {
                            clientHandler.handleViewThreadCase(forum, user);
                                logger.Info("Client chose to view forum threads");
                            }
                            catch(Exception ex)
                            {
                                Console.WriteLine("Failed to access server to view threads");
                                logger.Error("Failed to access server to view threads");
                                if (ex is SocketException)
                                {
                                    Console.WriteLine("Server unreachable");
                                    logger.Error("Server unreachable. User was logged out");
                                    ClientConfiguration.disconnectConfigure(ref forum);
                                    user = loginOrRegister(auth, ref logger, ref moderatorFlag);
                                }
                            }
                            break;
                        case "2":
                            clientHandler.handleAddThread(forum, user);
                            break;
                        case "3":
                            if (moderatorFlag)
                                clientHandler.handleRemoveThread(forum, user);
                            else
                                Console.WriteLine("Cannot Allow Remove");
                            break;
                        case "4":
                            try
                            {
                                clientHandler.handleEditFriendsList(forum, user, auth);
                            }
                            catch (Exception ex)
                            {
                                Console.WriteLine("Server unreachable");
                                logger.Error("Server unreachable. User was logged out");
                                ClientConfiguration.disconnectConfigure(ref forum);
                                moderatorFlag = false;
                                user = loginOrRegister(auth, ref logger, ref moderatorFlag);
                            }
                            break;
                        case "5":
                            logger.Info("UserName " + user.Username + " has been logout successfully");
                            ClientConfiguration.disconnectConfigure(ref forum);
                            moderatorFlag = false;
                            Console.WriteLine("logout successfully\n");
                            user = loginOrRegister(auth,ref logger, ref moderatorFlag);
                            if (user == null)
                                Console.WriteLine("could not locate server");
                            else
                                clientHandler.handleChooseAForum(ref forum,auth);//Choose an other forum
                            break;
                        case "6":
                            clientHandler.handleChooseAForum(ref forum,auth);//Choose an other forum
                            break;
                        case "7"://TODO: how do we exit gracefully here?
                            Console.WriteLine("Thank you for visting the forum");
                            Console.WriteLine("");
                            return;
                        default:
                            Console.WriteLine("Please choose a number and hit Enter");
                            Console.WriteLine("");
                            break;

                    }
                    
                }
            }

        }

        /// <summary>
        /// 
        /// read password as masked input
        /// </summary>
        /// <returns></returns>
        private static String readPassword()
        {
            String password = "";
            ConsoleKeyInfo info = Console.ReadKey(true);
            while (info.Key != ConsoleKey.Enter)
            {
                if (info.Key != ConsoleKey.Backspace)
                {
                    password += info.KeyChar;
                    info = Console.ReadKey(true);
                }
                else if (info.Key == ConsoleKey.Backspace)
                {
                    if (!string.IsNullOrEmpty(password))
                    {
                        password = password.Substring
                        (0, password.Length - 1);
                    }
                    info = Console.ReadKey(true);
                }
            }

            for (int i = 0; i < password.Length; i++)
                Console.Write("*");
            return password;
        }
        
        /// <summary>
        /// client login or registration
        /// </summary>
        /// <param name="auth">Authenticator</param>
        /// <returns>User if found, Null if failed</returns>
        public static User loginOrRegister(Authenticator auth, ref ILog logger, ref bool moderatorFlag)
        {
            bool regFlag = false;
            String tName;
            String tPass;
            User tUser;
            Console.WriteLine("What would you like to do?");
            Console.WriteLine("1.   Login");
            Console.WriteLine("2.   Register");
            Console.WriteLine("3.   Exit");
            String input = Console.ReadLine();
            while (true)
            {
                //-------------------------------login--------------------------------//
                if (input.Equals("1"))
                {
                    tUser = clientLogin(ref auth, ref moderatorFlag);
                    if (tUser != null)
                        break;
                }
                //-----------------------------Register-------------------------------//
                else if (input.Equals("2") && !regFlag)
                {
                    regFlag = true;
                    Console.WriteLine("");
                    Console.Write("Enter First Name: ");
                    String tFName = Console.ReadLine();
                    Console.Write("Enter Last Name: ");
                    String tLName = Console.ReadLine();
                    do
                    {
                        Console.Write("Enter User Name: ");
                        tName = Console.ReadLine();
                        Console.Write("Enter Password: ");
                        tPass = readPassword();
                        //Continue if name is not used already
                        if (!auth.checkName(tName))
                        {
                            tUser = new User(tName, tPass, "xxx@xxx.il", "132", tFName, tLName);
                            auth.registerUser(tUser);
                            break;
                        }
                        Console.WriteLine("");
                        Console.WriteLine("Username Exists, Choose Another");
                        Console.WriteLine("");
                    } while (true);
                    Console.WriteLine("");
                    Console.WriteLine("Registration Complete");
                    logger.Info("Client has been registerd as "+tUser.Username);
                }
                else if (input.Equals("3"))
                {
                    Console.WriteLine("");
                    Environment.Exit(0);//to do exit 
                }
                else
                {
                    Console.WriteLine("Wrong Selection!! (already registerd once??)");
                }
                Console.WriteLine("");
                Console.WriteLine("What would you like to do?");
                Console.WriteLine("1.   Login");
                Console.WriteLine("2.   Register");
                Console.WriteLine("3.   Exit");
                input = Console.ReadLine();
            }

            logger.Info("Client login as " + tUser.Username);
            Console.WriteLine("Login Complete: Welcome " + tUser.Username);
            Console.WriteLine("");
            return tUser;
        }

        public static User clientLogin(ref Authenticator auth, ref bool moderatorFlag)
        {
            String tName = "";
            String tPass = "";
            Console.WriteLine("Please Login");
            Console.Write("User Name: ");
            tName = Console.ReadLine();
            Console.Write("Password: ");
            tPass = readPassword();// Console.ReadLine();
            Console.WriteLine("");
            Console.WriteLine("");
            //Check user exists
            User tUser = auth.confirmLogin(tName, tPass);
            //-------if user is moderator
            if (tUser == null)
            {
                tUser = auth.confirmModeratorLogin(tName, tPass);
                moderatorFlag = true;
            }
            if (tUser == null)
                Console.WriteLine("Username or Password Incorrect");

            return tUser;
        }



    }
}
